package com.gagakuai.bpm.common.exception.handler;



import com.gagakuai.bpm.common.exception.BpmException;
import com.gagakuai.bpm.common.exception.EntityExistException;
import com.gagakuai.bpm.common.exception.HxException;
import com.gagakuai.bpm.domian.dto.response.ResponseStatusDto;
import com.gagakuai.bpm.utils.ThrowableUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /*
     * 处理所有不可知的异常
     */
    @ExceptionHandler(Throwable.class)
    public ResponseEntity<ApiError> handleException(Throwable e) {
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        return buildResponseEntity(ApiError.error(e.getMessage()));
    }

    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity<ApiError> handleAccessDeniedException(AccessDeniedException e) {
        log.error(ThrowableUtil.getStackTrace(e));
        return buildResponseEntity(ApiError.error(HttpServletResponse.SC_FORBIDDEN, "无权限访问该接口"));
    }

    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<ApiError> illegalArgumentException(IllegalArgumentException e) {
        log.error(ThrowableUtil.getStackTrace(e));
        return buildResponseEntity(ApiError.error("参数格式错误: 请输入正确的参数"));
    }

    @ExceptionHandler(BindException.class)
    public ResponseEntity<ApiError> bindException(BindException e) {
        log.error(ThrowableUtil.getStackTrace(e));
        return buildResponseEntity(ApiError.error("参数格式错误: 请输入正确的参数"));
    }


    /*
     * 处理bpm自定义异常
     */
    @ExceptionHandler(BpmException.class)
    public ResponseStatusDto bpmException(BpmException e) {
        ResponseStatusDto result = new ResponseStatusDto();

        if (e.getCodeEnum() != null) {
            int code = e.getCodeEnum().getCode();
            result.setCode(code + "");
            String message = e.getCodeEnum().getDescription();
            result.setMessage(message);

        } else if (Objects.nonNull(e.getCodeEnum())) {

            return result.setCode(e.getCodeEnum() + "");
        } else {
            Integer status = e.getStatus();
            result.setCode(status + "");
            result.setMessage(e.getMessage());
        }
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        return result;

    }

    /*
     * BadCredentialsException
     */
    @ExceptionHandler(BadCredentialsException.class)
    public ResponseStatusDto badCredentialsException(BadCredentialsException e) {
        // 打印堆栈信息
        String message = "坏的凭证".equals(e.getMessage()) ? "登录失败：您输入的用户名或密码错误，请重新输入并注意区分大小写。" +
                "如忘记密码，请联系系统管理员。" : e.getMessage();

        if (message.equals("用户名或密码错误")) {
            message = "登录失败：您输入的用户名或密码错误，请重新输入并注意区分大小写。" +
                    "如忘记密码，请联系系统管理员。";
        }

        ResponseStatusDto result = new ResponseStatusDto();

        result.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value() + "");
        result.setMessage(message);
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        return result;
    }

    /*
     * 处理自定义异常
     */
    @ExceptionHandler(value = HxException.class)
    public ResponseStatusDto badRequestException(HxException e) {

        ResponseStatusDto result = new ResponseStatusDto();

        if (e.getCodeEnum() != null) {
            int code = e.getCodeEnum().getCode();
            result.setCode(code + "");
            String message = e.getCodeEnum().getDescription();
            result.setMessage(message);

        } else if (Objects.nonNull(e.getCodeEnum())) {

            return result.setCode(e.getCodeEnum() + "");
        } else {
            Integer status = e.getStatus();
            result.setCode(status + "");
            result.setMessage(e.getMessage());
        }
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        return result;
    }

    /*
     * 处理io流异常
     */
    @ExceptionHandler(value = IOException.class)
    public ResponseStatusDto baIOException(IOException e) {

        ResponseStatusDto result = new ResponseStatusDto();
        result.setCode("500");
        result.setMessage("服务器I/O流错误");
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        return result;
    }

    /*
     * 处理 EntityExist
     */
    @ExceptionHandler(value = EntityExistException.class)
    public ResponseEntity<ApiError> entityExistException(EntityExistException e) {
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        return buildResponseEntity(ApiError.error(e.getMessage()));
    }


    /*
     * 处理 EntityNotFound
     */
  /*  @ExceptionHandler(value = EntityNotFoundException.class)
    public ResponseEntity<ApiError> entityNotFoundException(EntityNotFoundException e) {
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        return buildResponseEntity(ApiError.error(NOT_FOUND.value(), e.getMessage()));
    }*/

    /*
     * 处理所有接口数据验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ApiError> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\.");
        String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
        String msg = "不能为空";
        if (msg.equals(message)) {
            message = str[1] + ":" + message;
        }
        return buildResponseEntity(ApiError.error(message));
    }

    /*
     * 统一返回
     */
    private ResponseEntity<ApiError> buildResponseEntity(ApiError apiError) {
        return new ResponseEntity<>(apiError, HttpStatus.valueOf(apiError.getStatus()));
    }


    /* *//*
     * 参数合法性校验异常
     * @param exception
     * @return
     *//*
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public String validationBodyException(MethodArgumentNotValidException exception){

        StringBuffer buffer = new StringBuffer();

        BindingResult result  = exception.getBindingResult();
        if (result.hasErrors()) {

            List<ObjectError> errors = result.getAllErrors();

            errors.forEach(p ->{

                FieldError fieldError = (FieldError) p;
                log.error("Data check failure : object{"+fieldError.getObjectName()+"},field{"+fieldError.getField()+
                        "},errorMessage{"+fieldError.getDefaultMessage()+"}");
                buffer.append(fieldError.getDefaultMessage()).append(",");
            });
        }
         Result<String> response = new Result<>();
         response.setMessage(BusinessCodeEnum.INVALID_PARAM);
        return JSONObject.toJSONString(response);
    }*/
}
